#include "stdafx.h"

Bars::Bars(String ^sym_name, Account ^acc)
{
	symbolName = gcnew String(sym_name);
	account = acc;

	bars = gcnew array<Bar^>(GlobalVars::MAX_BARS);
	cur_bar = 0;

	ibHistoryTicker = -1;
	mostHigh = -1;
	mostLow = -1;
}

Bar^ Bars::operator[](int Index)
{
	return bars[Index];
}

void Bars::CreateTrigger(float triggerPrice, float stopLossCents, int qSize, Side sd)
{
	trigger = gcnew Trigger(symbolName, triggerPrice, stopLossCents, qSize, sd, account, this);
}

void Bars::ReqHistory(String ^frmWhen)
{
	if (ibHistoryTicker != -1) return;

	TWSLib::IContract ^ic = account->TwsPointer->CreateContract();

	ibHistoryTicker = account->TwsPointer->GetNewID();
	ic->symbol = symbolName;
	ic->exchange = "SMART";
	ic->currency = "USD";
	ic->secType = "STK";
	account->Tws->historicalData += gcnew AxTWSLib::_DTwsEvents_historicalDataEventHandler(this, &Bars::HistoryFromIB);
	account->Tws->reqHistoricalDataEx(ibHistoryTicker, ic, frmWhen, "1 D", "1 min", "TRADES", 1, 1);
}

void Bars::HistoryFromIB(System::Object^  sender, AxTWSLib::_DTwsEvents_historicalDataEvent^  e)
{
	if (e->reqId == ibHistoryTicker)
	{
		if (e->close == -1)
		{
			Trg->LimitP->UpdateProfits(false);
			cur_bar--;
			tmpBarOpen = bars[cur_bar]->Open;
			tmpBarHigh = bars[cur_bar]->High;
			tmpBarLow = bars[cur_bar]->Low;
			TWSLib::IContract ^ic = account->TwsPointer->CreateContract();

			ibRealTimeTicker = account->TwsPointer->GetNewID();
			ic->symbol = symbolName;
			ic->exchange = "SMART";
			ic->secType = "STK";
			ic->currency = "USD";
			account->Tws->realtimeBar += gcnew AxTWSLib::_DTwsEvents_realtimeBarEventHandler(this, &Bars::RealTimeFromIB);
			account->Tws->reqRealTimeBarsEx(ibRealTimeTicker, ic, 5, "TRADES", 1);
			return;
		}

		Bar ^binfo = gcnew Bar;

		binfo->Open = e->open;
		binfo->Close = e->close;
		binfo->High = e->high;
		binfo->Low = e->low;
		binfo->Date = GlobalVars::ConvertHistoryToDate(e->date);
		binfo->Time = GlobalVars::ConvertHistoryToTime(e->date);
		AddBar(binfo, false);
	}
}

void Bars::RealTimeFromIB(System::Object^ sender, AxTWSLib::_DTwsEvents_realtimeBarEvent^ e)
{
	if (e->tickerId == ibRealTimeTicker)
	{
		if (e->high > tmpBarHigh) tmpBarHigh = e->high;
		if (e->low < tmpBarLow) tmpBarLow = e->low;

		if (GlobalVars::ConvertServerToTime(e->time)->Substring(6,2) == "55")
		{
			Bar ^binfo = gcnew Bar;

			binfo->Open = tmpBarOpen;
			binfo->Close = e->close;
			binfo->High = tmpBarHigh;
			binfo->Low = tmpBarLow;
			binfo->Date = GlobalVars::ConvertServerToDate(e->time);
			binfo->Time = GlobalVars::ConvertServerToTime(e->time)->Substring(0, 6) + "00";
			AddBar(binfo, true);
		}
		if (GlobalVars::ConvertServerToTime(e->time)->Substring(6,2) == "00")
		{
			tmpBarOpen = e->open;
			tmpBarHigh = e->high;
			tmpBarLow = e->low;
		}
	}
}

void Bars::AddBar(Bar ^bar_info, bool move_stop)
{
	bars[cur_bar] = gcnew Bar;
	bars[cur_bar]->Open = bar_info->Open;
	bars[cur_bar]->Close = bar_info->Close;
	bars[cur_bar]->High = bar_info->High;
	bars[cur_bar]->Low = bar_info->Low;
	bars[cur_bar]->Time = bar_info->Time;
	bars[cur_bar]->Date = bar_info->Date;
	cur_bar++;
	if (mostHigh == -1) mostHigh = bar_info->High;
	if (mostLow == -1) mostLow = bar_info->Low;
	if (bar_info->High > mostHigh) mostHigh = bar_info->High;
	if (bar_info->Low < mostLow) mostLow = bar_info->Low;

	if (move_stop == true)
		if (Trg->TideStopStartAfter > 0)
			Trg->TideStopStartAfter--;
		else
			if (Trg->InActive == false)
				MoveStopLoss();

	if (cur_bar == 385 && Trg->InActive == false)
	{
		GlobalVars::frmP->lstErr->Items->Insert(0, GlobalTime::GetTime() + SymbolName + " - End Of Day StopLoss");
		Trg->CloseTrigger(true);
	}
}

void Bars::MoveStopLoss()
{
	int distanceToEnd = 390 - cur_bar;
	int i, j;
	float best_bar = -1;
	float movingStopLossSpread;

	distanceToEnd = Math::Sqrt(distanceToEnd) * Trg->TideStop;

	if (Trg->Trend == sLONG)
	{
		for (i = cur_bar - 1, j = i - distanceToEnd; i >= j && i >= 0; i--)
			if (bars[i]->Low < best_bar || best_bar == -1) best_bar = bars[i]->Low;

		movingStopLossSpread = Math::Round((double)(Trg->TideStopSpace * Trg->RiskByCents / 100), 2);
		if (best_bar - movingStopLossSpread > trigger->StopLossPrice)
		{
			GlobalVars::frmP->lstErr->Items->Insert( 0, GlobalTime::GetTime() + symbolName + " - Trailing StopLoss, Price moved to " + Convert::ToString(best_bar - movingStopLossSpread) + " from " + Convert::ToString(trigger->StopLossPrice) );
			trigger->StopLossPrice = best_bar - movingStopLossSpread;
		}
	}
	if (Trg->Trend == sSHORT)
	{
		for (i = cur_bar - 1, j = i - distanceToEnd; i >= j && i >= 0; i--)
			if (bars[i]->High > best_bar || best_bar == -1) best_bar = bars[i]->High;

		movingStopLossSpread = Math::Round((double)(Trg->TideStopSpace * Trg->RiskByCents / 100), 2);
		if (best_bar + movingStopLossSpread < trigger->StopLossPrice)
		{
			GlobalVars::frmP->lstErr->Items->Insert( 0, GlobalTime::GetTime() + symbolName + " - Trailing StopLoss, Price moved to " + Convert::ToString(best_bar + movingStopLossSpread) + " from " + Convert::ToString(trigger->StopLossPrice) );
			trigger->StopLossPrice = best_bar + movingStopLossSpread;
		}
	}
}